#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "player.h"
#include "prop.h"

/*初始化玩家*/
void InitPlayer(player* p)
{
    p->HPMax=30;             //生命上限
    p->HP = 30;             //生命值
    p->MP = 0;              //气力（普通攻击积攒气力，蓄力攻击消耗气力，选择消耗的气力层数，释放增幅后的攻击）
    p->attack = 10;         //攻击力
    p->def = 2;             //防御力

    p->x = 0;               //位置（横坐标）
    p->y = 0;               //位置(纵坐标)
    sscanf("  🤠 ","%s",p->symbol);                                  //图标

    p->exp = 0;             //经验
    p->level=0;                  //等级
    p->spt = 0;              //技能点
    p->gold = 100;                 //金币

    InitDynamicArray(&p->bag);   //背包
    InitWeapon(&p->wpn);         //武器
    InitArmor(&p->armor);        //防具
    InitItem(&p->item);          //道具

}

void ShopInterFace(player* p);
void SptInterface(player* p);


/*玩家动作*/
void PlayerMove(char* (*map)[MAPSIZE],player* p,DArray* ms)
{
    /*将原位置清空*/
    map[p->x][p->y] = " "; 
    char choise = 0;
    printf("请选择移动方向(w,a,s,d)\n p(进入商店),b(检查背包)\n r(穿脱武器),t(穿脱防具),y(使用道具),u(暂停菜单) \n");
    
    scanf(" %c",&choise);

    switch(choise)
    {
        case 'w':if(p->x>0)p->x--;break;
        case 's':if(p->x<MAPSIZE-1)p->x++;break;
        case 'a':if(p->y>0)p->y--;break;
        case 'd':if(p->y<MAPSIZE-1)p->y++;break;
        case 'p':ShopInterFace(p);break;
        case 'b':system("clear");ShowBag(p);break;
        case 'r':WeaponUse(p);break;
        case 't':ArmorUse(p);break;
        case 'y':ItemUse(p);break;
        case 'u':PuseInterface(p,ms,map);break;
        default: break;
    }

    /*附上新位置*/
    map[p->x][p->y] = "  🤠 ";
}


/*打印玩家状态*/
void PrintPlayerStatus(player* p)
{
    printf("角色:等级⭐:%d  生命值💝:%d/%d  攻击力✊:%d  气力🤞:%d  防御力🛡:%d\n",p->level,p->HP,p->HPMax,p->attack,p->MP,p->def);
    if(p->wpn.id!=0)
    printf("当前武器【%s】\n",p->wpn.name.string);
    if(p->armor.id!=0)
    printf("当前防具【%s】\n",p->armor.name.string);
}


/*升级系统*/
void LevelUp(player* p)
{
    if(p->exp>=(p->level+1)*30)
    {
        system("clear");
        p->level++;
        p->exp-=p->level*30;
        
        printf("等级提升至 %d 级！\n",p->level);
        printf("⭐⭐⭐⭐⭐⭐⭐\n");
        printf("获得 [%d] 点技能点!\n",p->level*2);
        p->spt+=p->level*2;
        int confirm = 0;
        printf("是否立即进行技能点分配? (后续亦可在背包中分配)\n");
        printf("1 是  2 否\n");
        scanf(" %d",&confirm);
        if(confirm == 1)
        {
            SptInterface(p);
        }
        else if(confirm == 2)
        {
            return;
        }
        sleep(1);
    }
}


/*技能点分配*/
void SptInterface(player* p)
{
    while(1)
    {
        system("clear");
        printf("————————————分配技能点——————————————");
        printf("                    当前剩余技能点💡 [%d]\n",p->spt);
        printf("每级强化消耗 1 点spt\n");
        printf("1、+2攻击力\n");
        printf("2、+6生命上限\n");
        printf("3、+1防御力\n");
        printf("                    按 q 退出分配界面\n");
        int choice = 0;
        scanf(" %d",&choice);
        int confirm = 0;
        switch(choice)
        {
            case 1:
                printf("是否将 1 点技能点分配至 攻击力?\n");
                printf("1 是  2 否\n");
                scanf(" %d",&confirm);
                if(confirm==1)
                {
                    if(p->spt>=1)
                    {
                        printf("提升了 2 点攻击力!\n");
                        p->attack+=2;
                        printf("攻击力 ✊ 提升至: [%d]\n",p->attack);
                        p->spt--;
                        sleep(2);
                        break;
                    }
                    else
                    {
                        printf("技能点不足!\n");
                        sleep(2);
                        break;
                    }
                    
                }
                else if(confirm == 2)
                {
                    break;
                }

            case 2:
                printf("是否将 1 点技能点分配至 生命上限?\n");
                printf("1 是  2 否\n");
                
                scanf(" %d",&confirm);
                if(confirm==1)
                {
                    if(p->spt>=1)
                    {
                        printf("提升了 6 点生命上限!\n");
                        p->HPMax+=6;
                        printf("生命上限 💗 提升至: [%d]\n",p->HPMax);
                        p->spt--;
                        sleep(2);
                        break;
                    }
                    else
                    {
                        printf("技能点不足!\n");
                        sleep(2);
                        break;
                    }
                }
                else if(confirm == 2)
                {
                    break;
                }

            case 3:
                printf("是否将 1 点技能点分配至 防御力?\n");
                printf("1 是  2 否\n");
                scanf(" %d",&confirm);
                if(confirm==1)
                {
                    if(p->spt>=1)
                    {
                        printf("提升了 1 点防御力!\n");
                        p->def+=1;
                        printf("防御力 🛡 提升至: [%d]\n",p->def);
                        p->spt--;
                        sleep(2);
                        break;
                    }
                    else
                    {
                        printf("技能点不足!\n");
                        sleep(2);
                        break;
                    }
                    
                }
                else if(confirm == 2)
                {
                    break;
                }

            case 'q':
                return;

            default:
                return;
                break;
        }

    }
   
}


/*背包系统的一组回调函数*/
void Showptr(void* ptr)
{
    prop* p = (prop*)ptr;
    if(p->type == Weapon)
    {
        weapon* w=(weapon*)p->ptr;
        printf("武器id: %d  武器名字: %s  攻击力：+%d\n",w->id,w->name.string,w->attack);
    }
    if(p->type == Defence)
    {
        defence* d =(defence*)p->ptr;
        printf("防具id: %d  防具名字: %s  防御力: +%d\n",d->id,d->name.string,d->defence);
    }
    if(p->type == Medicament)
    {
        medicament* m =(medicament*)p->ptr;
        printf("道具id: %d  道具名字: %s  回复量: %d\n",m->id,m->name.string,m->HP);
    }
}

void ShowArm(void* ptr)
{
    prop* p = (prop*)ptr;
    if(p->type == Defence)
    {
        defence* d =(defence*)p->ptr;
        printf("防具id: %d  防具名字: %s  防御力: +%d\n",d->id,d->name.string,d->defence);
    }
}

void ShowMed(void* ptr)
{
    prop* p = (prop*)ptr;
    if(p->type == Medicament)
    {
        medicament* m =(medicament*)p->ptr;
        printf("道具id: %d  道具名字: %s  回复量: %d\n",m->id,m->name.string,m->HP);
    }
}

void ShowWpn(void* ptr)
{
    prop* p = (prop*)ptr;
    if(p->type == Weapon)
    {
        weapon* w=(weapon*)p->ptr;
        printf("武器id: %d  武器名字: %s  攻击力：+%d\n",w->id,w->name.string,w->attack);
    }
}


/*按道具种类进行排序*/
bool SortByPropType(void* ptr1,void* ptr2)
{
    prop* p1 = (prop*)ptr1;
    prop* p2 = (prop*)ptr2;

    if(p1->type > p1->type)
    {
        return true;
    }
    return false;
}


/*检查背包状态*/
void ShowBag(player* p)
{
    p->bag.Sort(&p->bag,SortByPropType);
    printf("你的背包——————————————————————————————————————\n");
    printf("当前exp❇: %d  升级还需❇: %d  spt💡:%d 💰$%d\n",p->exp,((p->level+1)*30-p->exp),p->spt,p->gold);
    p->bag.DisplayDynamicArray(&p->bag,Showptr);
    printf("\n————————————————————————————————————————————\n");
    printf("按 k 分配技能点💡                        按 q 键退出\n");
    char choice;
    scanf(" %c",&choice);
    if(choice=='q')
    {
        return;
    }
    else if(choice == 'k')
    {
        SptInterface(p);
    }  
    
}


/*商店界面*/
void ShopInterFace(player* p)
{
    while(1)
    {
        system("clear");
        printf("——————————————————————————欢迎来到商店——————————————————————————————\n");
        printf("买点啥？                                               持有金币 [%d] \n\n",p->gold);
        printf("1.伊鲁席尔直剑 🗡   | 有概率使敌人冻伤, 无法做出行动 |   (攻击力+5) $10\n\n");
        printf("2.法棍 🥖   | 又硬又长,可以使用尾端对敌人进行追加攻击 |   (攻击力+2) $6\n\n");
        printf("3.药草 🌿   | 最经典的回复品之一 |                   (生命值+10) $5\n\n");
        printf("4.药丸 💊   | 浓缩的药草 |                          (生命值+20) $10\n\n");
        printf("5.屎块 💩   | 老练的地牢探险者偶尔会使用此物来避免被敌人攻击\n               如果能忍受恶臭的话,你不妨试试 |                   (垃圾) $1\n\n");
        printf("6.某人的日记📒|日常生活中发现此物, 还是不要随便翻阅为好。\n                  但这是在地牢中, 任何经验都弥足珍贵|            (经验+20) $10\n\n");
        printf("7.布甲👕    |它内部封印的东西对得起它的价格(店主的留言)|              (防御+1) $40\n\n");
        printf("8.链甲👕⛓  | 传统功夫讲究化劲儿|                      (防御+2) $20\n\n");
        printf("9.板甲👕🛡  |异常坚固，重量过重，不适合寻常人类穿着，但因此也可以用来防护非人的东西。|    (防御+5) $30\n\n");
        printf("                                                    按 q 退出商店\n");
        int choice = 0;
        scanf(" %d",&choice);

        switch(choice)
        {
            case 1: 
            sleep(1);
            if(p->gold<10)
            {
                printf("未持有足够的金币!\n");
                sleep(1);
                break;
            }
            printf("已购买【伊鲁席尔直剑】!\n");
            sleep(1);
            p->gold-=10;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Weapon,CreatWeapon(1,"伊鲁席尔直剑",5,Frozen)));

            break;

            case 2:
            sleep(1);
            if(p->gold<6)
            {
                printf("未持有足够的金币!\n");
                sleep(1);
                break;
            }
            printf("已购买【法棍】!\n");
            sleep(1);
            p->gold-=6;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Weapon,CreatWeapon(2,"法棍",2,DoubleAttack)));
            break;

            case 3: 
            sleep(1);
            if(p->gold<5)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【药草】!\n");
            sleep(1);
            p->gold-=5;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Medicament,CreatItem(1,"药草",10,-1)));
            break;

            case 4: 
            sleep(1);
            if(p->gold<10)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【药丸】!\n");
            sleep(1);
            p->gold-=10;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Medicament,CreatItem(2,"药丸",20,-1)));
            break;

            case 5: 
            sleep(1);
            if(p->gold<1)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【屎块】!\n");
            sleep(1);
            p->gold-=1;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Medicament,CreatItem(3,"屎块",-10,-1)));
            break;

            case 6: 
            sleep(1);
            if(p->gold<10)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【某人的日记】!\n");
            sleep(1);
            p->gold-=10;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Medicament,CreatItem(4,"某人的日记",0,-1)));
            break;


            case 7: 
            sleep(1);
            if(p->gold<10)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【布甲】!\n");
            sleep(1);
            p->gold-=10;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Defence,CreatDefence(1,"布甲",1,Reflex)));
            break;

            case 8: 
            sleep(1);
            if(p->gold<20)
            {
                printf("未持有足够的金币！\n");
                sleep(1);
                break;
            }
            printf("已购买【链甲】!\n");
            sleep(1);
            p->gold-=20;
            p->bag.InsertArrayTail(&p->bag,CreatProp(Defence,CreatDefence(2,"链甲",2,Charge)));
            break;

            case 9: 
                sleep(1);
                if(p->gold<30)
                {
                    printf("未持有足够的金币！\n");
                    sleep(1);
                    break;
                }
                printf("已购买【板甲】!\n");
                sleep(1);
                p->gold-=30;
                p->bag.InsertArrayTail(&p->bag,CreatProp(Defence,CreatDefence(3,"板甲",5,Weaken)));
                break;

            case 'q': 
                printf("别死太早,不然我的道具浪费了...\n");
                sleep(2);
                return;

            default:
                return;
                break;

        }
    }
    
}


/*释放道具空间的回调函数*/
void ClearProp(void* ptr)
{
    prop* t = (prop*)ptr;
    if(t->type == Weapon)
    {
        weapon* w = (weapon*)t->ptr;
        ClearString(&w->name);
        free(w);
    }
     if(t->type == Defence)
    {
        defence* d = (defence*)t->ptr;
        ClearString(&d->name);
        free(d);
    }
     if(t->type == Medicament)
    {
        medicament* m = (medicament*)t->ptr;
        ClearString(&m->name);
        free(m);
    }
}


/*根据名字找背包里的物品*/
bool CheckByName(void* ptr1,void* ptr2)
{
    char* s1 = (char*)ptr1;
    prop* s2 = (prop*)ptr2;
    if(s2->type == Weapon)
    {
        weapon* w=(weapon*)s2->ptr;
        if(IsContains(&w->name,s1)==true)
        return true;
    }
    if(s2->type == Defence)
    {
        defence* d=(defence*)s2->ptr;
        if(IsContains(&d->name,s1)==true)
        return true;
    }
    if(s2->type == Medicament)
    {
        medicament* m=(medicament*)s2->ptr;
        if(IsContains(&m->name,s1)==true)
        return true;
    }
    else
    return false;
}


/*装备和道具使用的一组函数*/
static int FrenchBred = 3;  //法棍能吃的次数
void WeaponUse(player* p)
{
   system("clear");
    if(p->wpn.id==0)
    {
        printf("选择需要装备的武器: \n");
        printf("或按 q 退出界面\n");
        p->bag.DisplayDynamicArray(&p->bag,ShowWpn);
        int choice = 0;
        scanf("%d",&choice);
        INITDARRAY(d);
        switch(choice)
        {
            case 1:
            
            d=p->bag.FindElement(&p->bag,(void*)"伊鲁席尔直剑",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已装备【伊鲁席尔直剑】!\n");
                sleep(2);
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"伊鲁席尔直剑",CheckByName,ClearProp);
                p->wpn.name.string = "伊鲁席尔直剑";
                p->wpn.id = 1;
                p->wpn.attack = 5;
                p->wpn.effect = Frozen;

                p->attack+=p->wpn.attack;
                
            }
            else
            {
                printf("未持有该武器!\n");
                sleep(2);
                return;
            }
            break;

            case 2:
            
            d=p->bag.FindElement(&p->bag,(void*)"法棍",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已装备【法棍】!\n");
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"法棍",CheckByName,ClearProp);
                p->wpn.name.string = "法棍";
                p->wpn.id = 2;
                p->wpn.attack = 2;
                p->wpn.effect = DoubleAttack;

                p->attack+=p->wpn.attack;
                //法棍隐藏效果，回复8血量
                if(FrenchBred!=0)
                {
                    printf("尝了一口法棍，回复了 [%d] 点生命值!\n",(p->HPMax-p->HP<3)?(p->HPMax-p->HP):3);
                    sleep(2);
                    /*不让回复量溢出*/
                    if(p->HPMax-p->HP<3)
                    {
                        p->HP=p->HPMax;
                    }
                    else
                    {
                        p->HP+=3;
                    }
                    FrenchBred--;
                }
                else
                {
                    printf("法棍居然被你吃完了!\n");
                    sleep(1);
                    printf("获得成就【来道硬菜!】\n");
                    sleep(2);
                    FrenchBred = 3;
                    p->attack-=2;
                    InitWeapon(&p->wpn);
                    p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"法棍",CheckByName,ClearProp);
                }
            }
            else
            {
                printf("未持有该武器!\n");
                sleep(2);
                return;
            }
            break;

            case 'q': return; break;

            default:
            break;
        }
    }
    else
    {
        int confirm = 0;
        printf("是否卸下当前已装备的武器【%s】? \n (1:是 or 2:否) \n",p->wpn.name.string);
        scanf("%d",&confirm);
        if(confirm == 1)
        {
            p->attack-=p->wpn.attack;
            printf("已卸下【%s】!\n",p->wpn.name.string);
            p->bag.InsertArrayTail(&p->bag,CreatProp(Weapon,CreatWeapon(p->wpn.id,p->wpn.name.string,p->wpn.attack,p->wpn.effect)));
            sleep(2);
            
            InitWeapon(&p->wpn);
          
        }
        if(confirm == 2)
        {
            return;
        }
    }
}

void ArmorUse(player* p)
{
    system("clear");
    if(p->armor.id==0)
    {
        printf("选择需要装备的防具: \n");
        printf("或按 q 退出界面\n");
        p->bag.DisplayDynamicArray(&p->bag,ShowArm);
        int choice = 0;
        scanf("%d",&choice);
        INITDARRAY(d);
        switch(choice)
        {
            case 1:
            
            d=p->bag.FindElement(&p->bag,(void*)"布甲",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已装备【布甲】!\n");
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"布甲",CheckByName,ClearProp);
                sleep(2);
                p->armor.name.string = "布甲";
                p->armor.id = 1;
                p->armor.defence = 1;
                p->armor.effect = Reflex;

                p->def+=p->armor.defence;
                
            }
            else
            {
                printf("未持有该防具!\n");
                sleep(2);
                return;
            }
            
            break;

            case 2:
            d=p->bag.FindElement(&p->bag,(void*)"链甲",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已装备【链甲】!\n");
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"链甲",CheckByName,ClearProp);
                sleep(2);
                p->armor.name.string = "链甲";
                p->armor.id = 2;
                p->armor.defence = 2;
                p->armor.effect = Charge;

                p->def+=p->armor.defence;
                
            }
            else
            {
                printf("未持有该防具!\n");
                sleep(2);
                return;
            }
            break;

            case 3:
            d=p->bag.FindElement(&p->bag,(void*)"板甲",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已装备【板甲】!\n");
                 p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"板甲",CheckByName,ClearProp);
                sleep(1);
                p->armor.name.string = "板甲";
                p->armor.id = 3;
                p->armor.defence = 5;
                p->armor.effect = Weaken;

                p->def+=p->armor.defence;
                printf("由于【板甲】太过沉重, 无法自如挥动武器！(攻击力下降了 [2] !)\n");
                sleep(2);
                p->attack-=2;

            }
            else
            {
                printf("未持有该防具!\n");
                sleep(2);
                return;
            }

            break;

            case 'q':  return; break;

            default:
            break;
        }
    }
    else
    {
        int confirm = 0;
        printf("是否卸下当前已装备的防具【%s】? \n (1:是 or 2:否) \n",p->armor.name.string);
        scanf("%d",&confirm);
        if(confirm == 1)
        {
            if(p->armor.id==3)
            p->attack+=2;
            p->def-=p->armor.defence;
            printf("已卸下【%s】!\n",p->armor.name.string);
            p->bag.InsertArrayTail(&p->bag,CreatProp(Defence,CreatDefence(p->armor.id,p->armor.name.string,p->armor.defence,p->armor.effect)));
            sleep(2);
            // ClearProp(&p->wpn);
            InitArmor(&p->armor);
          
        }
        if(confirm == 2)
        {
            return;
        }
    }

}

void ItemUse(player* p)
{
    system("clear");
    if(p->item.id==0)
    {
        printf("选择需要使用的道具: \n");
        printf("或按 q 退出\n");
        p->bag.DisplayDynamicArray(&p->bag,ShowMed);
        int choice = 0;
        scanf("%d",&choice);
        INITDARRAY(d);
        
        switch(choice)
        {
            case 1:
            d=p->bag.FindElement(&p->bag,(void*)"药草",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已使用【药草】!\n");
                
                p->item.name.string = "药草";
                p->item.id = 1;
                p->item.HP = 10;

                printf("回复了[%d]点生命值\n",(p->HPMax-p->HP<p->item.HP)?(p->HPMax-p->HP):(p->item.HP));
                sleep(2);
                /*防止回复量溢出*/
                if(p->HPMax-p->HP<p->item.HP)
                {
                    p->HP=p->HPMax;
                }
                else
                {
                    p->HP+=p->item.HP;
                }
                
                InitItem(&p->item);
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"药草",CheckByName,ClearProp);

            }
            else
            {
                printf("未持有该道具!\n");
                sleep(2);
                return;
            }
            
            break;

            case 2:
            d=p->bag.FindElement(&p->bag,(void*)"药丸",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已使用【药丸】!\n");

                p->item.name.string = "药丸";
                p->item.id = 2;
                p->item.HP = 20;

                printf("回复了[%d]点生命值\n",(p->HPMax-p->HP<p->item.HP)?(p->HPMax-p->HP):(p->item.HP));
                sleep(2);
                /*防止回复量溢出*/
                if(p->HPMax-p->HP<p->item.HP)
                {
                    p->HP=p->HPMax;
                }
                else
                {
                    p->HP+=p->item.HP;
                }
                
                InitItem(&p->item);
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"药丸",CheckByName,ClearProp);
            }
            else
            {
                printf("未持有该道具!\n");
                sleep(2);
                return;
            }
            break;

            case 3:
            d=p->bag.FindElement(&p->bag,(void*)"屎块",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已涂抹【屎块】!\n");

                p->item.name.string = "屎块";
                p->item.id = 3;
                p->item.HP = -10;
                if(GetRand(2)==1)
                {
                    printf("未能抵抗恶臭\n");
                    sleep(1);
                    printf("受到了[%d]点伤害\n",p->item.HP);
                    /*防止回复量溢出*/
                    p->HP+=p->item.HP;
                    p->HPMax+=p->item.HP;
                }
                else
                {
                    printf("忍受了恶臭, 防御力增加 [2] 点!\n");
                    p->def+=2;
                }
                sleep(2);
                InitItem(&p->item);
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"屎块",CheckByName,ClearProp);
            }
            else
            {
                printf("未持有该道具!\n");
                sleep(2);
                return;
            }
            
            break;

            case 4:
            d=p->bag.FindElement(&p->bag,(void*)"某人的日记",CheckByName);
            if(d.dp!=NULL)
            {
                printf("已使用【某人的日记】!\n");

                p->item.name.string = "某人的日记";
                p->item.id = 4;
                p->item.HP = 0;

                
                printf("获得了 [%d] 点经验值\n",20);
                p->exp+=20;
                sleep(2);
                InitItem(&p->item);
                p->bag.RemoveFirstArray_ByElement(&p->bag,(void*)"某人的日记",CheckByName,ClearProp);
            }
            else
            {
                printf("未持有该道具!\n");
                sleep(2);
                return;
            }
            
            break;


            case 'q': return; break;

            default:
            break;
        }
    }
}


/*气力重击系统*/
void MPAttack(player* p,monster* m)
{
    printf("当前剩余气力点🤞 :[%d]\n",p->MP);
    printf("请选择消耗的气力层数(1~3): \n");
    int Charge = 0;
    scanf(" %d",&Charge);
    if(p->MP>=Charge)
    {
        printf("消耗了 %d 层气力, 对【%s】发动蓄力攻击💥!\n",Charge,m->name.string);
        sleep(1);
        printf("【%s】受到了 %d 点伤害!\n",m->name.string,(DAMAGE(p,m)>0?DAMAGE(p,m):0)*Charge);
        sleep(1);
        m->HP-= (DAMAGE(p,m)>0?DAMAGE(p,m):0)*Charge;

        p->MP-=Charge;

        int WpnEffect = WeaponEffect(p,m);
        if(WpnEffect==Frozen)
            {
                return;
            }
        if(m->HP>0)
            {
                printf("【%s】对你发起了反击, 造成了 %d 点伤害\n",m->name.string,(DAMAGE(m,p)>0?DAMAGE(m,p):0));
                sleep(1);
                p->HP-=(DAMAGE(m,p)>0?DAMAGE(m,p):0);
                ArmorEffect(p,m);        
            }
    }
    else
    {
        printf("高估了自己的气力! 导致体内的【气】断流😱!\n");
        sleep(1);
        printf("进入【力竭】状态, 气力值归零!\n");
        sleep(1);
        p->MP = 0;

         if(m->HP>0)
            {
                printf("【%s】趁机对你发起了强力反击,造成了 %d 点伤害\n",m->name.string,2*(DAMAGE(m,p)>0?DAMAGE(m,p):0));
                sleep(1);
                p->HP-=(DAMAGE(m,p)>0?DAMAGE(m,p):0)*2;
                ArmorEffect(p,m);
                        
            }
    }

}


/*人物状态储存到字符串*/
mystr PlayerToString(player* p)
{
   char str[2048] = {0};
   sprintf(str,"%d %d %d %d %d %d %d %d %d %d %d %s\n",p->HPMax,p->HP,p->MP,p->attack,p->def,p->x,p->y,p->exp,p->level,p->spt,p->gold,p->symbol);

   /*身上的装备*/

        char wpn[100] = {0};
        sprintf(wpn,"%d %d %d %s\n",p->wpn.effect,p->wpn.attack,p->wpn.id,p->wpn.name.string);
        strcat(str,wpn);    

        char armor[100] = {0};
        sprintf(armor,"%d %d %d %s\n",p->armor.effect,p->armor.defence,p->armor.id,p->armor.name.string);
        strcat(str,armor);    

   /*包里的物品*/
   for(int i=0;i<p->bag.len;i++)
   {
        char prp[128]={0};
        prop* pro = p->bag.dp[i];
        if(pro->type==Weapon)
        {
            mystr s=WeaponToString((weapon*)pro->ptr);
            strcat(str,s.string);
            ClearString(&s);
        }

        if(pro->type==Defence)
        {
            mystr s=ArmorToString((defence*)pro->ptr);
            strcat(str,s.string);
            ClearString(&s);
        }

         if(pro->type==Medicament)
        {
            mystr s=ItemToString((medicament*)pro->ptr);
            strcat(str,s.string);
            ClearString(&s);
        }
   }

   return GetString(str);
}

//从存档复制人物状态到游戏
void StringToPlayer(mystrlist* ply,player* p)
{
    InitPlayer(p);
    int effect1=0;
    int effect2=0;
    //解析人物状态数据
    sscanf(ply->stringlist[0].string,"%d %d %d %d %d %d %d %d %d %d %d %s",&p->HPMax,&p->HP,&p->MP,&p->attack,&p->def,&p->x,&p->y,&p->exp,&p->level,&p->spt,&p->gold,p->symbol);
    
    //解析已穿戴的装备数据
    char temp1 = 0;
    temp1 = ply->stringlist[1].string[0];
    effect1 = atoi(&temp1);
    if(effect1<=4&&effect1>=1)
    {
        //sscanf在解析字符串的时候，遇到要写入的参数宽度不够，会自动停止
        ResizeString(&p->wpn.name,32);   //拓宽
        sscanf(ply->stringlist[1].string,"%d %d %d %s",(int*)&p->wpn.effect,&p->wpn.attack,&p->wpn.id,p->wpn.name.string);
    }
    if(effect1>=5&&effect1<=7)
    {   ResizeString(&p->armor.name,32);
        sscanf(ply->stringlist[1].string,"%d %d %d %s",(int*)&p->armor.effect,&p->armor.defence,&p->armor.id,p->armor.name.string);
    }

    char temp2 = 0;
    temp2 = ply->stringlist[2].string[0];
    effect2 = atoi(&temp2);
    if(effect2<=4&&effect2>=1)
    {
        ResizeString(&p->wpn.name,32);
        sscanf(ply->stringlist[2].string,"%d %d %d %s",(int*)&p->wpn.effect,&p->wpn.attack,&p->wpn.id,p->wpn.name.string);
    }
    if(effect2>=5&&effect2<=7)
    {   
        ResizeString(&p->armor.name,32);
        sscanf(ply->stringlist[2].string,"%d %d %d %s",(int*)&p->armor.effect,&p->armor.defence,&p->armor.id,p->armor.name.string);
    }

    //解析背包数据
    for(int i=3;i<ply->len;i++)
    {
        int TempType = 0;
        char TempName[20] = {0};
        int TempValue = 0;
        int TempId = 0;
        int TempEffect = 0;
        sscanf(ply->stringlist[i].string,"%d %s %d %d %d",&TempType,TempName,&TempValue,&TempId,&TempEffect);
        if(TempType == Weapon)
        {
            p->bag.InsertArrayTail(&p->bag,CreatProp(Weapon,CreatWeapon(TempId,TempName,TempValue,TempEffect)));
        }
        if(TempType == Defence)
        {
            p->bag.InsertArrayTail(&p->bag,CreatProp(Defence,CreatDefence(TempId,TempName,TempValue,TempEffect)));
        }
        if(TempType == Medicament)
        {
            p->bag.InsertArrayTail(&p->bag,CreatProp(Medicament,CreatItem(TempId,TempName,TempValue,TempEffect)));
        }
    }
}


/*存档*/
void SaveGame(player* p,DArray* m)
{
    mystr ply =PlayerToString(p);
    mystr mst =MonsterToString(m);
    // printf("%s\n",mst.string);
    while(1)
    {
        printf("请选择要覆盖的存档!\n");
        printf("1、Save1   2、Save2   3、Save3\n");
        int choice = 0;
        scanf("%d",&choice);
        switch(choice)
        {
            case 1:
                mystrlist namelist1 = GetLineFromFile("playername.txt");
                char Save1[20];
                char SaveMonster1[20];
                sprintf(Save1,"Save1%s.txt",namelist1.stringlist[0].string);
                sprintf(SaveMonster1,"Save1%s_m.txt",namelist1.stringlist[0].string);

                if((WriteToFile(ply.string,Save1,ply.len)==true)
                &&(WriteToFile(mst.string,SaveMonster1,mst.len)==true))
                printf("已保存至存档栏位 1!\n");
                else
                {
                    printf("存档失败!\n");
                    sleep(1);
                }
                ClearMyStringList(&namelist1);
                return;
            break;
            case 2:
                mystrlist namelist2 = GetLineFromFile("playername.txt");
                char Save2[20];
                char SaveMonster2[20];
                sprintf(Save2,"Save2%s.txt",namelist2.stringlist[0].string);
                sprintf(SaveMonster2,"Save2%s_m.txt",namelist2.stringlist[0].string);

                if((WriteToFile(ply.string,Save2,ply.len)==true)
                &&(WriteToFile(mst.string,SaveMonster2,mst.len)==true))
                printf("已保存至存档栏位 2!\n");
                else
                {
                    printf("存档失败!\n");
                    sleep(1);
                }
                ClearMyStringList(&namelist2);
                return;
            break;
            case 3:
                mystrlist namelist3 = GetLineFromFile("playername.txt");
                char Save3[20];
                char SaveMonster3[20];
                sprintf(Save3,"Save3%s.txt",namelist3.stringlist[0].string);
                sprintf(SaveMonster3,"Save3%s_m.txt",namelist3.stringlist[0].string);

                if((WriteToFile(ply.string,Save3,ply.len)==true)
                &&(WriteToFile(mst.string,SaveMonster3,mst.len)==true))
                printf("已保存至存档栏位 3!\n");
                else
                {
                    printf("存档失败!\n");
                    sleep(1);
                }
                ClearMyStringList(&namelist3);
                return;
            break;
            default:
            break;
        }
    }
}

/*读档*/
bool LoadGame(player* p,DArray* m)
{
        system("clear");
        printf("————————————读取存档————————————\n");
        printf("请选择要加载的存档!\n");
        printf("1、Save1   2、Save2   3、Save3\n");
        printf("                     按 q 退出\n");
        int choice = 0;
        scanf("%d",&choice);
        switch(choice)
        {
            case 1:
            mystrlist namelist1 = GetLineFromFile("playername.txt");
            char Save1[20];
            char SaveMonster1[20];
            sprintf(Save1,"Save1%s.txt",namelist1.stringlist[0].string);
            sprintf(SaveMonster1,"Save1%s_m.txt",namelist1.stringlist[0].string);
            ClearMyStringList(&namelist1);

            mystrlist ply1;
            InitMyStrList(&ply1);
            FILE* fp1;
            fp1 = fopen(Save1,"r");
            if(fp1 == NULL)
            {
                printf("未读取到人物存档1!\n");
                sleep(2);
                ClearMyStringList(&namelist1);
                break;
            }
            ply1 = GetLineFromFile(Save1);
           
            StringToPlayer(&ply1,p);
            ClearMyStringList(&ply1);

            mystrlist mst1;
            InitMyStrList(&mst1);
            FILE* fm1;
            fm1 = fopen(SaveMonster1,"r");
            if(fm1 == NULL)
            {
                printf("未读取到怪物存档1!\n");
                sleep(2);
                ClearMyStringList(&namelist1);
 
                break;
            }
            mst1 = GetLineFromFile(SaveMonster1);

            StringToMonster(&mst1,m);
            ClearMyStringList(&mst1);
            ClearMyStringList(&namelist1);
            return true;
            break;
            
            case 2:
            mystrlist namelist2 = GetLineFromFile("playername.txt");
            char Save2[20];
            char SaveMonster2[20];
            sprintf(Save2,"Save2%s.txt",namelist2.stringlist[0].string);
            sprintf(SaveMonster2,"Save2%s_m.txt",namelist2.stringlist[0].string);
            ClearMyStringList(&namelist2);

            mystrlist ply2;
            InitMyStrList(&ply2);
            FILE* fp2;
            fp2 = fopen(Save2,"r");
            if(fp2 == NULL)
            {
                printf("未读取到人物存档2!\n");
                sleep(2);
                ClearMyStringList(&namelist2);
                break;
            }
            ply2 = GetLineFromFile(Save2);
          
            StringToPlayer(&ply2,p);
            ClearMyStringList(&ply2);

            mystrlist mst2;
            InitMyStrList(&mst2);
            FILE* fm2;
            fm2 = fopen(SaveMonster2,"r");
            if(&fm2 == NULL)
            {
                printf("未读取怪物到存档2!\n");
                sleep(2);
                ClearMyStringList(&namelist2);
                break;
            }
            mst2 = GetLineFromFile(SaveMonster2);
       
            StringToMonster(&mst2,m);
            ClearMyStringList(&mst2);
            ClearMyStringList(&namelist2);
            return true;
            break;

            case 3:
            mystrlist namelist3 = GetLineFromFile("playername.txt");
            char Save3[20];
            char SaveMonster3[20];
            sprintf(Save3,"Save3%s.txt",namelist3.stringlist[0].string);
            sprintf(SaveMonster3,"Save3%s_m.txt",namelist3.stringlist[0].string);
            ClearMyStringList(&namelist3);

            mystrlist ply3;
            InitMyStrList(&ply3);
            FILE* fp3;
            fp3 = fopen(Save3,"r");
            if(fp3 == NULL)
            {
                printf("未读取到人物存档3!\n");
                sleep(2);
                ClearMyStringList(&namelist3);
                break;
            }
            ply3 = GetLineFromFile(Save3);

            StringToPlayer(&ply3,p);
            ClearMyStringList(&ply3);

            mystrlist mst3;
            InitMyStrList(&mst3);
            FILE* fm3;
            fm3 = fopen(SaveMonster3,"r");
            if(fm3 == NULL)
            {
                printf("未读取到怪物存档3!\n");
                sleep(2);
                ClearMyStringList(&namelist3);
                break;
            }
            mst3 = GetLineFromFile(SaveMonster3);

            StringToMonster(&mst3,m);
            ClearMyStringList(&mst3);

            ClearMyStringList(&namelist3);
            return true;
            break;

            case 'q':
                return false;
                break;

            default:
                break;
        }
    return false;
}


/*暂停菜单*/
void PuseInterface(player* p,DArray* ms,char* (*map)[MAPSIZE])
{
    system("clear");
    printf("————————————————游戏已暂停——————————————————\n");
    printf("做何操作?\n\n");
    printf("1.继续游戏\n");
    printf("2.保存游戏\n");
    printf("3.载入游戏\n");
    printf("4.保存并退出\n\n");

    int choice = 0;
    scanf(" %d",&choice);

    switch(choice)
    {
        case 1:
        return;

        case 2:
        SaveGame(p,ms);
        break;

        case 3:
        if(LoadGame(p,ms)==true)
        {
            InitMap(map);
            ResetMonsterSPosition(ms,map);
        }
        break;

        case 4:
        SaveGame(p,ms);
        printf("——————————游戏结束!——————————\n");
        sleep(1);
        exit(0);
        break;

        default:
        break;

    }

}


/*武器特效*/
int WeaponEffect(player* p,monster* m)
{
    int choice = 0;
    choice=p->wpn.effect;
    switch(choice)
    {
        /*冻伤(50%概率)(固定受到3点伤害，一回合无法做出行动)*/
        case Frozen:
            if(GetRand(2)==1)
            {
                printf("【%s】获得了【冻伤❄】效果!\n",m->name.string);
                printf("承受了 [%d] 的寒冷伤害。\n",3);
                m->HP-=3;
                sleep(1);
                printf("由于【冻伤❄】, 【%s】未能发动反击!\n",m->name.string);
                sleep(1);
                return Frozen;
            }
            break;
        /*二连打(75%概率二连打)*/
        case DoubleAttack:
            if(GetRand(4)!=0)
            {
                printf("【%s】使用起来十分顺手, 对【%s】追加了一次打击\n",p->wpn.name.string,m->name.string);
                sleep(1);
                m->HP-=(DAMAGE(p,m)>0?DAMAGE(p,m):0)/2;
                printf("【%s】再次受到了 [%d] 的追加伤害\n",m->name.string,(DAMAGE(p,m)>0?DAMAGE(p,m):0)/2);
                sleep(1);
                return DoubleAttack;
            }
            break;

        default:
        return -1;
        break;

    }
}


/*防具特效*/
int ArmorEffect(player* p,monster* m)
{
    int choice = 0;
    choice = p->armor.effect;
    switch(choice)
    {
        /*返还伤害,伤害量为怪物对你造成的伤害，加上你的护甲值的总和，除以二*/
        case Reflex:
            printf("【%s】的攻击使【再生刺甲】变得不稳定,溅出棘刺射向【%s】\n",m->name.string,m->name.string);
            sleep(1);
            printf("【%s】受到了 [%d] 的溅射伤害!\n",m->name.string,(DAMAGE(m,p)+p->def)/2);
            sleep(1);
            m->HP-=(DAMAGE(m,p)+p->def)/2;
            return Reflex;
            break;

        /*使怪物手臂酸软(攻击力固定下降1)*/
        case Weaken:
            printf("【%s】由于坚硬的质地,震得【%s】虎口生疼,【%s】进入【手臂酸软】状态!\n",p->armor.name.string,m->name.string,m->name.string);
            sleep(1);
            printf("【%s】的攻击力下降了 1 点!\n",m->name.string);
            sleep(1);
            m->attack--;
            return Weaken;
            break;

        /*受击固定加 1 点血量上限*/
        case Charge:
            printf("【%s】承受了攻击, 冲击力在内部转化, 使你变得更有活力了!\n",p->armor.name.string);
            printf("生命值上限增加了 1 \n");
            sleep(1);
            p->HPMax++;
            return Charge;
            break;

        default:
            break;
    }
}


